package com.xsomnus.rpc.consumer.config.rpc;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xsomnus.rpc.common.common.Constants;
import com.xsomnus.rpc.common.entity.Request;
import com.xsomnus.rpc.common.entity.Response;
import com.xsomnus.rpc.common.util.IdUtil;
import com.xsomnus.rpc.consumer.netty.NettyClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Map;

/**
 * @author @xsomnus666_xiawenye★
 * @since 2019/4/22 0022 17:49
 * 当你发现自己的才华撑不起野心时，就请安静下来学习吧
 */
@Slf4j
@Component
public class RPCFactory<T> implements InvocationHandler {

    @Autowired
    NettyClient nettyClient;

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Request request = new Request();
        request.setClassName(method.getDeclaringClass().getSimpleName());
        request.setMethodName(method.getName());
        request.setParameters(args);
        request.setParameterTypes(method.getParameterTypes());
        request.setId(IdUtil.getId());
        log.debug("[consumer] request: {}", request);
        Object ret = nettyClient.send(request);

        Class<?> returnType = method.getReturnType();

        Response response = JSON.parseObject(ret.toString(), Response.class);

        if (response.getCode() == Constants.ERROR_CODE) {
            throw new Exception(response.getErrMsg());
        }

        if (returnType.isPrimitive() || String.class.isAssignableFrom(returnType)) {
            // 判断返回类型是否为基本类型 (九种预定义的Class对象代表的八个基本类型和void) 和 是否为String的子类
            return response.getData();
        } else if (Collection.class.isAssignableFrom(returnType)) {
            // 判断返回类型是否为集合类型
            return JSONArray.parseObject(response.getData().toString(), Object.class);
        } else if (Map.class.isAssignableFrom(returnType)) {
            // 判断返回类型是否为Map类型
            return JSON.parseObject(response.getData().toString(), Map.class);
        } else {
            // 若为其他类型,直接返回
            Object data = response.getData();
            log.debug("data: {}", data.toString());
            return JSONObject.parseObject(data.toString(), returnType);
        }
    }
}
